/*******************************************************************************
 * The MOSES project, model based software engineering of networked embedded systems.
 * 
 * Copyright (C) 2010-2013, University of Applied Sciences Wildau,
 * Telematics Research Group, http://www.tm.th-wildau.de/research-group
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses>.
 * 
 * Contributors:
 *     University of Applied Sciences Wildau - initial API and implementation
 * 
 * If you are interested in a commercial license please contact us via 
 * e-mail: ralf.vandenhouten@th-wildau.de.
 ******************************************************************************/
package de.thwildau.tm.moses.examples.nmea.data;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import de.thwildau.tm.moses.abnf.io.AbnfCoder;

/**
 * The GP-GGA (Global Positioning System Fix Data, Time, Position and fix related data fora GPS receiver)
 * class of NMEA.
 * <p>
 * The structure is:
 * 
 * <pre>
 *  $GPGGA,014457,3739.853,N,12222.821,W,1,03,5.4,1.1,M,-28.2,M,,*7E         
 *  $aaGGA,hhmmss.ss,llll.ll,a,gggg.gg,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh(CR)(LF)
 *         |         |       | |       | | |  |   |   | |   | |   |
 *         |         |       | |       | | |  |   |   | |   | |   Differential reference station ID
 *         |         |       | |       | | |  |   |   | |   | Age of differential GPS data (seconds) 
 *         |         |       | |       | | |  |   |   | |   Unit of geodial separation, meters
 *         |         |       | |       | | |  |   |   | Geodial separation
 *         |         |       | |       | | |  |   |   Unit of antenna altitude, meters
 *         |         |       | |       | | |  |   Antenna altitude above sea level
 *         |         |       | |       | | |  Horizontal dilution of precision
 *         |         |       | |       | | number of satellites in use 00-12 (in use, not in view!)
 *         |         |       | |       | GPS quality indicator (0:invalid, 1:GPS fix, 2:DGPS fix)
 *         |         |       | Longitude Orientation  (E - East or W - West)
 *         |         Latitude| Orientation  (N - North or S - South) 
 *         UTC of position
 * </pre>
 * 
 * Another decription from http://www.nmea.de/nmea0183datensaetze.html:
 * 
 * <pre>
 *        1         2       3 4        5 6 7  8   9  10 |  12 13  14   15
 *        |         |       | |        | | |  |   |   | |   | |   |    |
 * $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
 * 
 * Field Number: 
 *  1) Universal Time Coordinated (UTC)
 *  2) Latitude
 *  3) N or S (North or South)
 *  4) Longitude
 *  5) E or W (East or West)
 *  6) GPS Quality Indicator,
 *     0 - fix not available,
 *     1 - GPS fix,
 *     2 - Differential GPS fix
 *  7) Number of satellites in view, 00 - 12
 *  8) Horizontal Dilution of precision
 *  9) Antenna Altitude above/below mean-sea-level (geoid) 
 * 10) Units of antenna altitude, meters
 * 11) Geoidal separation, the difference between the WGS-84 earth
 *     ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level
 *     below ellipsoid
 * 12) Units of geoidal separation, meters
 * 13) Age of differential GPS data, time in seconds since last SC104
 *     type 1 or 9 update, null field when DGPS is not used
 * 14) Differential reference station ID, 0000-1023
 * 15) Checksum
 * 
 * <pre>
 * <p>  
 *
 * @author Thomas Kistel
 * @version $Revision: 764 $
 */
public class GpGga extends Nmea {

    private Float utcTime;
    private Float latitude;
    private LatitudeOrientation latitudeOrientation;
    private Float longitude;
    private LongitudeOrientation longitudeOrientation;
    private GpsQuality gpsQuality;
    private Integer amountSatellites;
    private Float horizontalDilution;
    private Float antennaAltitude;
    private Float geodialSeparation;
    private Float ageOfDGPS;
    private Integer referenceStationId;


    public Float getUtcTime() {
        return utcTime;
    }

    public void setUtcTime(Float utcTime) {
        this.utcTime = utcTime;
    }

    public Float getLatitude() {
        return latitude;
    }

    public void setLatitude(Float latitude) {
        this.latitude = latitude;
    }

    public LatitudeOrientation getLatitudeOrientation() {
        return latitudeOrientation;
    }

    public void setLatitudeOrientation(LatitudeOrientation latitudeOrientation) {
        this.latitudeOrientation = latitudeOrientation;
    }

    public Float getLongitude() {
        return longitude;
    }

    public void setLongitude(Float longitude) {
        this.longitude = longitude;
    }

    public LongitudeOrientation getLongitudeOrientation() {
        return longitudeOrientation;
    }

    public void setLongitudeOrientation(LongitudeOrientation longitudeOrientation) {
        this.longitudeOrientation = longitudeOrientation;
    }

    public GpsQuality getGpsQuality() {
        return gpsQuality;
    }

    public void setGpsQuality(GpsQuality gpsQuality) {
        this.gpsQuality = gpsQuality;
    }

    public Integer getAmountSatellites() {
        return amountSatellites;
    }

    public void setAmountSatellites(Integer amountSatellites) {
        this.amountSatellites = amountSatellites;
    }

    public Float getHorizontalDilution() {
        return horizontalDilution;
    }

    public void setHorizontalDilution(Float horizontalDilution) {
        this.horizontalDilution = horizontalDilution;
    }

    public Float getAntennaAltitude() {
        return antennaAltitude;
    }

    public void setAntennaAltitude(Float antennaAltitude) {
        this.antennaAltitude = antennaAltitude;
    }

    public Float getGeodialSeparation() {
        return geodialSeparation;
    }

    public void setGeodialSeparation(Float geodialSeparation) {
        this.geodialSeparation = geodialSeparation;
    }

    public Float getAgeOfDGPS() {
        return ageOfDGPS;
    }

    public void setAgeOfDGPS(Float ageOfDGPS) {
        this.ageOfDGPS = ageOfDGPS;
    }

    public Integer getReferenceStationId() {
        return referenceStationId;
    }

    public void setReferenceStationId(Integer referenceStationId) {
        this.referenceStationId = referenceStationId;
    }

    @Override
    public void read(DataInput in) throws IOException {
        this.utcTime = AbnfCoder.decodeUntil(in, ",", Float.class);
        this.latitude = AbnfCoder.decodeUntil(in, ",", Float.class);
        this.latitudeOrientation = AbnfCoder.decode(in, LatitudeOrientation.values());
        AbnfCoder.checkDecode(in, ",");
        this.longitude = AbnfCoder.decodeUntil(in, ",", Float.class);
        this.longitudeOrientation = AbnfCoder.decode(in, LongitudeOrientation.values());
        AbnfCoder.checkDecode(in, ",");
        this.gpsQuality = AbnfCoder.decode(in, GpsQuality.values());
        AbnfCoder.checkDecode(in, ",");
        this.amountSatellites = AbnfCoder.decodeUntil(in, ",", Integer.class);
        this.horizontalDilution = AbnfCoder.decodeUntil(in, ",", Float.class);
        this.antennaAltitude = AbnfCoder.decodeUntil(in, ",", Float.class);
        AbnfCoder.checkDecode(in, "M,");
        this.geodialSeparation = AbnfCoder.decodeUntil(in, ",", Float.class);
        AbnfCoder.checkDecode(in, "M,");
        this.ageOfDGPS = AbnfCoder.decodeUntil(in, ",", Float.class);
        this.referenceStationId = AbnfCoder.decodeUntil(in, "*", Integer.class);
        String checksum = AbnfCoder.decode(in, 2);
        this.checksum = Integer.valueOf(checksum, 16);
    }

    @Override
    public void write(DataOutput out) throws IOException {
        throw new UnsupportedOperationException("Not implemented.");
        // AbnfCoder.encode(out, "$");
        // AbnfCoder.encode(out, alphas);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(time));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(latitude));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, latns);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(longitude));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, lonew);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, quality);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, satellites);
        // AbnfCoder.encode(out, Float.toString(hdop));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(height));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, heightUnit);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(hovergeoid));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, unitsofgeoidal);
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, Float.toString(ageofdata));
        // AbnfCoder.encode(out, ",");
        // AbnfCoder.encode(out, referencestationid);
        // AbnfCoder.encode(out, "*");
        // AbnfCoder.encode(out, checkSum);
        // AbnfCoder.encode(out, CoreRules.CRLF);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("$GPGGA");
        builder.append(",").append(utcTime);
        builder.append(",").append(latitude);
        builder.append(",").append(latitudeOrientation);
        builder.append(",").append(longitude);
        builder.append(",").append(longitudeOrientation);
        builder.append(",").append(gpsQuality);
        builder.append(",").append(amountSatellites);
        builder.append(",").append(horizontalDilution);
        builder.append(",").append(antennaAltitude);
        builder.append(",").append(geodialSeparation);
        builder.append(",").append(ageOfDGPS);
        builder.append(",").append(referenceStationId);
        return builder.toString();
    }
}
